
/////////////////////////////////////////////////////////////////////////////

#ifndef __FOLDERDLG_H__
#define __FOLDERDLG_H__

#if defined( _MSC_VER ) && ( _MSC_VER >= 1020 )
	#pragma once
#endif

// Uncomment if using GetRootFolder
#ifndef _INC_SHLWAPI
	#include < shlwapi.h >
#endif
#pragma comment( lib, "shlwapi.lib" )

/////////////////////////////////////////////////////////////////////////////

#ifndef		SAFE_DELETE2
	#define SAFE_DELETE2( p ) \
		if( p ){ delete[] p; p = NULL; }
#endif

#ifndef		SAFE_ZEROMEMORY
	#define SAFE_ZEROMEMORY( p, size ) \
		if( p ){ ZeroMemory( p, size ); }
#endif

#ifndef		SAFE_COTASKMEMFREE
	#define SAFE_COTASKMEMFREE( p ) \
		if( p ){ CoTaskMemFree( (LPVOID)p ); p = NULL; }
#endif


/////////////////////////////////////////////////////////////////////////////

class CFolderDialog 
{
public:
	CFolderDialog(	LPCTSTR	pszTitle	= NULL, 
					LPCTSTR	pszSelPath	= NULL,
					HWND	hWndParent	= NULL,
					UINT		uFlags		= BIF_RETURNONLYFSDIRS )
					:m_hWnd(NULL)
	{
		::ZeroMemory( &m_bi, sizeof( BROWSEINFO ) );
		::ZeroMemory( m_szFolPath, MAX_PATH );
		::ZeroMemory( m_szSelPath, MAX_PATH );

		m_bi.hwndOwner	= hWndParent;
		m_bi.pidlRoot	= NULL;
		m_bi.lpszTitle	= pszTitle;
		m_bi.ulFlags	= uFlags;
		m_bi.lpfn		= (BFFCALLBACK)&BrowseCallbackProc;
		m_bi.lParam		= (LPARAM)this;
		m_bi.pszDisplayName = new TCHAR[ MAX_PATH ];
		SAFE_ZEROMEMORY( 
			m_bi.pszDisplayName, ( MAX_PATH * sizeof( TCHAR ) )
		);

		if( pszSelPath )
			SetSelectedFolder( pszSelPath );
	}

	virtual ~CFolderDialog( VOID )
	{
		SAFE_COTASKMEMFREE( m_bi.pidlRoot );
		SAFE_DELETE2( m_bi.pszDisplayName );
		::ZeroMemory( &m_bi, sizeof( BROWSEINFO ) );
	}

public:
	#if ( _MFC_VER >= 0x0700 )	// VC++ 2002 (7.0)
		virtual INT_PTR		DoModal( VOID )
	#else
		virtual INT			DoModal( VOID )
	#endif
		{
			INT_PTR nRet = -1;
			LPITEMIDLIST pItemIDList = ::SHBrowseForFolder( &m_bi );
			if( pItemIDList )
			{
				if( ::SHGetPathFromIDList( pItemIDList, m_szFolPath ) )
					nRet = IDOK;
				SAFE_COTASKMEMFREE( pItemIDList );
			}
			else
				nRet = IDCANCEL;
			return ( nRet );
		}

	BOOL	SetSelectedFolder( IN LPCTSTR pszPath )
	{
		return (BOOL)::lstrcpy( m_szSelPath, pszPath );
	}

public:	
	LPCTSTR	GetFolderPath( VOID )  const;
	LPCTSTR	GetFolderName( VOID )  const;
	INT		GetFolderImage( VOID ) const;		
	LPCTSTR	GetSelectedFolder( VOID ) const;

	BROWSEINFO&		 GetBI( VOID );
	const BROWSEINFO& GetBI( VOID ) const;

protected:	
	BROWSEINFO	m_bi;
	TCHAR	m_szSelPath[ MAX_PATH ];
	TCHAR	m_szFolPath[ MAX_PATH ];
	HWND	m_hWnd; // used only in the callback function


protected: // Overridables
	virtual VOID OnInitialized( VOID )
	{
		if( ::lstrlen( m_szSelPath ) > 0 )
			SetSelection( m_szSelPath );
	}
	VOID SetSelection( IN LPCTSTR pszPath )
	{
		::SendMessage(m_hWnd, BFFM_SETSELECTION, (WPARAM)TRUE, (LPARAM)pszPath);
	}

private:
	static INT CALLBACK BrowseCallbackProc(
		IN HWND hWnd, IN UINT uMsg, IN LPARAM lParam, IN LPARAM lpData
	)
	{
		CFolderDialog* pThis = (CFolderDialog*)lpData;
		INT nRet = 0;
		pThis->m_hWnd = hWnd;
		switch( uMsg )
		{
		case BFFM_INITIALIZED:
			pThis->OnInitialized();
			break;	
		}
		pThis->m_hWnd = NULL;
		return nRet;
	}
};

/////////////////////////////////////////////////////////////////////////////

inline LPCTSTR CFolderDialog::GetSelectedFolder( VOID ) const
	{ return m_szSelPath; }

inline BROWSEINFO& CFolderDialog::GetBI( VOID )
	{ return m_bi; }

inline const BROWSEINFO& CFolderDialog::GetBI( VOID ) const
	{ return m_bi; }

/////////////////////////////////////////////////////////////////////////////
// Filled after a call to DoModal

inline LPCTSTR CFolderDialog::GetFolderPath( VOID ) const
	{ return m_szFolPath; }

inline LPCTSTR CFolderDialog::GetFolderName( VOID ) const
	{ return m_bi.pszDisplayName; }

inline INT CFolderDialog::GetFolderImage( VOID ) const
	{ return m_bi.iImage; }

/////////////////////////////////////////////////////////////////////////////
#endif // __FOLDERDLG_H__
/////////////////////////////////////////////////////////////////////////////